package com.wlf.server.web.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.wlf.server.common.context.BeanContext;
import com.wlf.server.common.em.Const;
import com.wlf.server.common.entity.SysUser;
import com.wlf.server.common.service.SysMenuService;
import com.wlf.server.common.service.SysUserService;
import com.wlf.server.web.util.AjaxBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 菜单的渲染，
 */

@Slf4j
@RestController
@RequestMapping("/main")
public class IndexController {
    @Resource
    SysMenuService menuService;
    @Resource
    CaptchaService captchaService;
    @Resource
    SysUserService userService;
    @Resource
    BeanContext beanContext;

    /**
     * 这个值可以弄成配置的，也可以弄成不定时间更换的。
     */
    final String encodeHexStr = "qeNm3eXK/BCAwTVoEjfaGQ==";

    /**
     * 获取前端加密的字符春
     * 这个可以不定期的 改动解析规则
     */
    @GetMapping("/login")
    AjaxBean getLogin() {
        return AjaxBean.getOkData(encodeHexStr);
    }

    /**
     * 登录入口
     *
     * @param key                 用户k
     * @param passwd              密码
     * @param captchaVerification 验证码
     * @return 登录结果
     */
    @PostMapping("/login")
    AjaxBean postLogin(String key, String passwd, String captchaVerification) {
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(captchaVerification);
        ResponseModel response = captchaService.verification(captchaVO);
        log.info(response.toString());
        if (!response.isSuccess()) {
            return AjaxBean.getError(response.getRepMsg());
        }
        SysUser user = userService.lambdaQuery()
                // 登录账号
                .eq(SysUser::getLoginNo, key).or()
                // 或者手机号
                .eq(SysUser::getPhone, key)
                .one();
        if (user == null) {
            return AjaxBean.getError("用户名或密码不正确，登陆失败！");
        }
        //构建
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, encodeHexStr.getBytes(StandardCharsets.UTF_8));
        // 解密出前台传递过来的原始密码
        String decryptStr = aes.decryptStr(passwd, CharsetUtil.CHARSET_UTF_8);
        // 暂时数据库不加密
        if (!decryptStr.equals(user.getPassword())) {
            return AjaxBean.getError("用户名或密码不正确，登陆失败！");
        }

        StpUtil.login(user.getId(), Const.LoginType.PC.name());
        SysUser updateUser = new SysUser();
        updateUser.setId(user.getId());
        updateUser.setLoginEndTime(LocalDateTime.now());
        userService.updateById(updateUser);
        // 返回登录信息
        return AjaxBean.getOkMsg("登录成功", Dict.create()
                .set("token", StpUtil.getTokenInfo()));
    }

    /**
     * 注销登录
     */
    @GetMapping("/logout")
    AjaxBean logout() {
        StpUtil.logout();
        return AjaxBean.getOkMsg("退出登录成功");
    }

    /**
     * 侧边栏菜单加载
     * // {
     * // 	id: '12345',		// 菜单id, 必须唯一
     * // 	name: '用户中心',		// 菜单名称, 同时也是tab选项卡上显示的名称
     * // 	icon: 'el-icon-user',	// 菜单图标, 参考地址:  <a href="https://element.eleme.cn/#/zh-CN/component/icon">https://element.eleme.cn/#/zh-CN/component/icon</a>
     * //	info: '管理所有用户',	// 菜单介绍, 在菜单预览和分配权限时会有显示
     * // 	url: 'sa-view/user/user-list.html',	// 菜单指向地址
     * // 	parentId: 1,			// 所属父菜单id, 如果指定了一个值, sa-admin在初始化时会将此菜单转移到指定菜单上
     * // 	isShow: true,			// 是否显示, 默认true
     * // 	isBlank: false,		// 是否属于外部链接, 如果为true, 则点击菜单时从新窗口打开
     * // 	childList: [			// 指定这个菜单所有的子菜单, 子菜单可以继续指定子菜单, 至多支持四级菜单
     * // 		// ....
     * // 	],
     * //	click: function(){}		// 点击菜单执行一个函数
     * // }
     * 项目主界面的初始化，包括菜单，登录人员信息等
     */
    @GetMapping("/init")
    AjaxBean init() {
        TreeNodeConfig tConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        tConfig.setIdKey("id");
        tConfig.setChildrenKey("childList");
        tConfig.setNameKey("name");
        // 最大递归深度
        tConfig.setDeep(4);
        List<Tree<String>> menuList = menuService.getTree(menuService.getSysMenuByLoginUser(), tConfig);

        return AjaxBean.getOkData(Dict.create()
                .set("menuList", menuList)
                .set("userDTO", userService.getUserByLogin()));
    }

    /**
     * 登录页根据登录ID获取头像
     *
     * @param key 登录ID
     * @return 头像
     */
    @GetMapping("/avatar")
    public AjaxBean avatar(String key) {
        SysUser user = userService.lambdaQuery()
                // 登录账号
                .eq(SysUser::getLoginNo, key).or()
                // 或者手机号
                .eq(SysUser::getPhone, key).one();
        if (user == null) {
            return AjaxBean.getOkMsg();
        }
        if (StrUtil.isBlank(user.getAvatar())) {
            return AjaxBean.getOkMsg();
        }
        return AjaxBean.getOkData(user.getAvatar());
    }

    /**
     * 清理Redis缓存，有时候更新代码逻辑后，出现类型转换异常时
     * 可调用此API清理Redis中的缓存
     */
    @GetMapping("/clean-cache")
    AjaxBean cleanCache() {
        beanContext.cleanCache();
        return AjaxBean.getOkMsg("清理成功");
    }
}
